﻿namespace eg_082_多态
{
    /*
     * 面向对象的另一特性：多态。
     * 多态性具体表现在两个方面，
     * 前面的实例中已经出现了其中的一种，
     * 就是将派生类的实例分配给其基类对象的引用，
     * 将派生类对象作为基类对象处理，
     * 此时该对象的声明类型为基类，
     * 而运行时类型为派生类；
     * 多态性的另一方面是基类可以定义并实现虚方法，
     * 派生类可以重写这些方法来提供自己的定义和实现。
     * 在程序运行时调用虚方法的重写方法，
     * 系统会检查对象的运行时类型，
     * 就算使用的是基类对象，
     * 但运行时类型是派生类，
     * 程序同样会执行派生类中重写的方法。
     */
    internal class Program
    {    //圆形
        class Circle
        {
            protected int radius;                                //半径
            public Circle(int radius) { this.radius = radius; }  //构造圆形
            /* 定义虚方法
             * 1：抽象方法仅仅是声明,没有任何实现内容；抽象方法一般必须在子类中被重写以后才有使用价值
                2：针对抽象方法引出的问题：如果需要在父类中提供一个方法，该方法有自己的方法体，子类根据自己的需要决定是否重写该方法，而不是必须重写，这就是 ‘虚方法’
                3：使用关键字virtual修改时的虚方法
             */
            public virtual double Area() { return Math.PI * radius * radius; }   //计算面积
        }
        //圆柱体
        class Cylinder : Circle
        {
            int high;
            public Cylinder(int radius, int high) : base(radius) //构造圆柱
            {
                this.high = high;
            }
            public override double Area()                        //重写计算面积函数
            {
                //计算圆柱体表面积=两个底面圆面积+侧面矩形面积
                return base.Area() * 2 + 2 * Math.PI * radius * high;
            }
        }
        //圆锥体
        class Cone : Circle
        {
            int high;
            public Cone(int radius, int high)
              : base(radius)                                        //构造圆柱
            {
                this.high = high;
            }
            public override double Area()                            //重写计算面积函数
            {
                double line = Math.Sqrt(radius * radius + high * high);   //计算母线长
                                                                          //计算圆锥体表面积=底面圆面积+侧面扇形面积
                return base.Area() * Math.PI * radius * line;
            }
        }
        static void Main(string[] args)
        {
            Circle cylinder = new Cylinder(100, 100);               //实例化圆柱体
            Console.WriteLine("半径为100高为100的圆柱体表面积为{0:N2}", cylinder.Area());
            Circle cone = new Cone(100, 100);                       //实例化圆锥体
            Console.WriteLine("半径为100高为100的圆锥体表面积为{0:N2}", cone.Area());
        }
    }
}